/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package image.diffussion;

import image.processing.ImageProcessor;
import image.utils.ImageUtilitiesImpl;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

/**
 *
 * @author tommy
 */
public abstract class DiffusionImpl implements Diffusion {
	protected BufferedImage src;
	protected BufferedImage ret;
	public DiffusionImpl(BufferedImage src) {
		ret = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
		this.src = ImageUtilitiesImpl.getInstance().addPaddingEdge(src, 1);
	}
	
	public BufferedImage diffuse(int t) {
		BufferedImage aux = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
		WritableRaster auxRaster = aux.getRaster();
		int[][][] diffPixels;
		boolean isColor;

		
		src.copyData(auxRaster); // clone padded border from src to aux
		WritableRaster outRaster = ret.getRaster();
		
		diffPixels = new int[3][ret.getHeight()][ret.getWidth()];
		
		Raster inRaster = src.getData();
		isColor = src.getType() == BufferedImage.TYPE_3BYTE_BGR || src.getType() == BufferedImage.TYPE_4BYTE_ABGR;
		
		for (int i = 0 ; i < t ; i++) {
			for (int y = 1 ; y < src.getHeight() -1 ; y++) {
				for (int x = 1 ; x < src.getWidth() - 1 ; x++) {
					if (!isColor) {
						diffPixels[0][y-1][x-1] = (int)getDiffusedPixel(i,x,y,0,inRaster);
					} else {
						diffPixels[0][y-1][x-1] = (int)getDiffusedPixel(i,x,y,0,inRaster);
						diffPixels[1][y-1][x-1] = (int)getDiffusedPixel(i,x,y,1,inRaster);
						diffPixels[2][y-1][x-1] = (int)getDiffusedPixel(i,x,y,2,inRaster);
					}
				}
			}
			
			if (!isColor) {
				diffPixels[0] = ImageProcessor.LinearRangeCompressionChannel(diffPixels[0]);
			} else {
				diffPixels[0] = ImageProcessor.LinearRangeCompressionChannel(diffPixels[0]);
				diffPixels[1] = ImageProcessor.LinearRangeCompressionChannel(diffPixels[1]);
				diffPixels[2] = ImageProcessor.LinearRangeCompressionChannel(diffPixels[2]);
			}
			
			// medio ineficiente esta forma de hacerlo, refactorear luego
			for (int y = 1 ; y < src.getHeight() -1 ; y++) {
				for (int x = 1 ; x < src.getWidth() - 1 ; x++) {
					if (!isColor) {
						auxRaster.setSample(x, y, 0, diffPixels[0][y-1][x-1]);
						outRaster.setSample(x-1, y-1, 0, diffPixels[0][y-1][x-1]);
					} else {
						auxRaster.setSample(x, y, 0, diffPixels[0][y-1][x-1]);
						outRaster.setSample(x-1, y-1, 0, diffPixels[0][y-1][x-1]);
						auxRaster.setSample(x, y, 1, diffPixels[1][y-1][x-1]);
						outRaster.setSample(x-1, y-1, 1, diffPixels[1][y-1][x-1]);
						auxRaster.setSample(x, y, 2, diffPixels[2][y-1][x-1]);
						outRaster.setSample(x-1, y-1, 2, diffPixels[2][y-1][x-1]);
					}
				}
			}
			inRaster = aux.getData(); // next t, image@t+1
		}
		
			
		return ret;
	}
	
	/*
	 * Anisotropic and Isotropic difference is in constant * gradient(I(x,y)).
	 */
	protected abstract double getDiffusedPixel(int t, int x, int y, int b, Raster inRaster);
}
